/*
 * Copyright (c) 2022 FuZhou Lockzhiner Electronic Co., Ltd. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cJSON.h>
#include "ohos_init.h"
#include "los_task.h"
#include "oc_mqtt.h"
#include "e53_intelligent_agriculture.h"
#include "lz_hardware.h"
#include "config_network.h"

//定义路由器的SSID
#define ROUTE_SSID                      "HUAWEI-Y3SKJ3_HiLink"
// 定义路由器的密码
#define ROUTE_PASSWORD                  "czuky203"

// 定义消息队列的长度
#define MSG_QUEUE_LENGTH                16
// 定义缓冲区的长度
#define BUFFER_LEN                      50

// 定义客户端ID
#define CLIENT_ID                       "6691159b5830dc113ecc3084_E53_IA_0_0_2024071606"
// 定义用户名
#define USERNAME                        "6691159b5830dc113ecc3084_E53_IA"
// 定义密码
#define PASSWORD                        "1f764a5c8ddd634868cfa7473fb8fe2216e1e84a6a17d942c3504291319e863e"



#define TEXT        "XiaoZhiPai!"
#define WEB         "fzlzdz.com"
typedef struct
{
    int lum;
    int temp;
    int hum;
    int soil;
} ia_report_t;

typedef struct
{
    en_msg_type_t msg_type;
    cmd_t cmd;
    ia_report_t report;
} ia_msg_t;

typedef struct
{
    int connected;
    int led;
    int motor;
    int fun;
    int waterpump;
} ia_status_t;


extern uint8_t iowild_status;
extern uint8_t iowater_status;
extern uint8_t iosoild_status;


/**************************************** */
EVENT_CB_S event_wild;
EVENT_CB_S event_water;
static unsigned int m_ia_MsgQueue;
static ia_status_t m_app_status;
//消息队列
unsigned int lcd_msg;
extern EVENT_CB_S lcd_event;
e53_ia_data_t e53_ia_data;
/**************************************** */









/***************************************************************
* 函数名称: ia_deal_report_msg
* 说    明: 上报智慧农业模块数据到华为云上
* 参    数: report：智慧农业上报消息指针
* 返 回 值: 无
***************************************************************/
void ia_deal_report_msg(ia_report_t *report)
{
    oc_mqtt_profile_service_t service;
    // 定义温度变量
    oc_mqtt_profile_kv_t temperature;
    // 定义湿度变量
    oc_mqtt_profile_kv_t humidity;
    // 定义光照强度变量
    oc_mqtt_profile_kv_t luminance;
    // 定义LED变量
    oc_mqtt_profile_kv_t led;
    // 定义电机变量
    oc_mqtt_profile_kv_t motor;

    oc_mqtt_profile_kv_t fun;
    oc_mqtt_profile_kv_t Soil;
    oc_mqtt_profile_kv_t Waterpump;

    // 初始化service结构体
    service.event_time = NULL;
    // 设置service_id为"智慧农业"
    service.service_id = "智慧农业";
    // 设置service_property为temperature
    service.service_property = &temperature;
    // 设置nxt为NULL
    service.nxt = NULL;
    // 设置温度的键
    temperature.key = "温度";
    // 设置温度的值
    temperature.value = &report->temp;
    // 设置温度的类型为整型
    temperature.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    // 设置温度的下一个节点为湿度
    temperature.nxt = &humidity;

    humidity.key = "湿度";
    humidity.value = &report->hum;
    humidity.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    humidity.nxt = &luminance;

    luminance.key = "亮度";
    luminance.value = &report->lum;
    luminance.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    luminance.nxt = &led;

    led.key = "紫光灯状态";
    led.value = m_app_status.led ? "开" : "关";
    led.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    led.nxt = &motor;

    motor.key = "电机状态";
    motor.value = m_app_status.motor ? "开" : "关";
    motor.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    motor.nxt = &fun;
    
    fun.key = "风扇状态";
    fun.value = m_app_status.fun ? "开" : "关";
    fun.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    fun.nxt = &Soil;

    Soil.key = "土壤湿度";
    Soil.value = &report->soil;
    Soil.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    Soil.nxt = &Waterpump;

    Waterpump.key = "水泵状态";
    Waterpump.value = m_app_status.waterpump ? "开" : "关";
    Waterpump.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
    Waterpump.nxt = NULL;



    // 调用oc_mqtt_profile_propertyreport函数，传入用户名和服务的指针
    oc_mqtt_profile_propertyreport(USERNAME, &service);
}

/***************************************************************
* 函数名称: ia_cmd_response_callback
* 说    明: 华为云命令处理回调函数
* 参    数: recv_data：接收的数据指针
*           recv_size：接收数据的大小
*           resp_data：响应数据的指针
*           resp_size：响应数据的大小
* 返 回 值: 无
***************************************************************/

void ia_cmd_response_callback(uint8_t *tpc_data, size_t tpc_size,uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size)
{
    ia_msg_t *app_msg = NULL;
    int ret = 0;

    app_msg = malloc(sizeof(ia_msg_t));
    if (app_msg == NULL)
    {
        printf("malloc msg fail");
        return;
    }
    app_msg->msg_type = en_msg_cmd;
    app_msg->cmd.payload = (char *)recv_data;
    //app_msg->cmd.request_id = "1598a4bf-510b-466a-bd8c-a9b86f2cce50";

    printf("recv data is %.*s\n", tpc_size, tpc_data);
    const char *start = tpc_data +tpc_size-36;
    // printf("start is %d\n", start);
    // printf("start is %d\n", &tpc_data[tpc_size-36]);
    // 复制n个字符
    char *reid;
    reid = malloc(37);
    strncpy(reid, start, 36);
    reid[36] = '\0';
    //printf("reid is %s\n", reid);
    app_msg->cmd.request_id=reid;
   

    if (LOS_OK != LOS_QueueWrite(m_ia_MsgQueue, (void *)app_msg, sizeof(ia_msg_t), 0))
    {
        printf("%s LOS_QueueWrite fail\n", __func__);
        free(recv_data);
        free(app_msg);
    }
    *resp_data = NULL;
    *resp_size = 0;
}

/***************************************************************
* 函数名称: ia_deal_cmd_msg
* 说    明: 处理华为云下发的命令
* 参    数: cmd：华为云下发的命令结构体指针
* 返 回 值: 无
***************************************************************/
void ia_deal_cmd_msg(cmd_t *cmd)
{
    //printf("reid1:%x\n",reid1);
   // printf("%s\n",cmd->payload->)
    cJSON *obj_root;
    cJSON *obj_cmdname;
    cJSON *obj_paras;
    cJSON *obj_para;
    int cmdret = 1;
    oc_mqtt_profile_cmdresp_t cmdresp;

    obj_root = cJSON_Parse(cmd->payload);
    if (obj_root == NULL)
    {
        goto EXIT_JSONPARSE;
    }
    // cJSON_Print(obj_root);
    // printf("=============\n");
    // //printf("", cmd->payload);
    obj_cmdname = cJSON_GetObjectItem(obj_root, "command_name");
    if (obj_cmdname == NULL)
    {
        goto EXIT;
    }
    if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "紫光灯控制"))
    {
        obj_paras = cJSON_GetObjectItem(obj_root, "paras");
        if (obj_paras == NULL)
        {
            goto EXIT;
        }
        obj_para = cJSON_GetObjectItem(obj_paras, "Light");
        if (obj_para == NULL)
        {
            goto EXIT;
        }
        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            m_app_status.led = 1;
            light_set(ON);
            printf("Light On\n");
        }
        else
        {
            m_app_status.led = 0;
            light_set(OFF);
            printf("Light Off\n");
        }
        cmdret = 0;
    }
    else if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "电机控制"))
    {
        // 获取Paras对象
        obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
        // 如果Paras对象为空，则跳转到EXIT
        if (obj_paras == NULL)
        {
            goto EXIT;
        }
        // 获取Motor对象
        obj_para = cJSON_GetObjectItem(obj_paras, "Motor");
        // 如果Motor对象为空，则跳转到EXIT
        if (obj_para == NULL)
        {
            goto EXIT;
        }
        // 如果Motor对象的值为"ON"，则设置电机状态为ON
        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            m_app_status.motor = 1;
            motor_set_status(ON);
            printf("Motor On\n");
        }
        // 否则，设置电机状态为OFF
        else
        {
            m_app_status.motor = 0;
            motor_set_status(OFF);
            printf("Motor Off\n");
        }
        // 设置命令返回值为0
        cmdret = 0;
    }
    else if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "风扇控制"))
    {
        // 获取Paras对象
        obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
        // 如果Paras对象为空，则跳转到EXIT
        if (obj_paras == NULL)
        {
            goto EXIT;
        }
        // 获取Motor对象
        obj_para = cJSON_GetObjectItem(obj_paras, "Fun");
        // 如果Motor对象为空，则跳转到EXIT
        if (obj_para == NULL)
        {
            goto EXIT;
        }
        // 如果Motor对象的值为"ON"，则设置电机状态为ON
        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            m_app_status.fun = 1;
            LOS_EventWrite(&event_wild, 0x00000001);
            LOS_EventClear(&event_wild,~event_wild.uwEventID);
            printf("Fun On\n");
        }
        // 否则，设置电机状态为OFF
        else
        {
            m_app_status.fun = 0;
            LOS_EventWrite(&event_wild, 0x10000001); 
            LOS_EventClear(&event_wild,~event_wild.uwEventID);
            printf("Fun Off\n");
        }

        // 设置命令返回值为0
        cmdret = 0;
    }
    else if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "水泵控制"))
    {
        // 获取Paras对象
        obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
        // 如果Paras对象为空，则跳转到EXIT
        if (obj_paras == NULL)
        {
            goto EXIT;
        }
        // 获取Motor对象
        obj_para = cJSON_GetObjectItem(obj_paras, "Waterpump");
        // 如果Motor对象为空，则跳转到EXIT
        if (obj_para == NULL)
        {
            goto EXIT;
        }
        // 如果Motor对象的值为"ON"，则设置电机状态为ON
        if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
        {
            m_app_status.waterpump = 1;
            LOS_EventWrite(&event_water, 0x00000001);
            LOS_EventClear(&event_water,~event_water.uwEventID);
            printf("Waterpump On\n");
        }
        // 否则，设置电机状态为OFF
        else
        {
            m_app_status.waterpump = 0;
            LOS_EventWrite(&event_water, 0x10000001); 
            LOS_EventClear(&event_water,~event_water.uwEventID);
            printf("Waterpump Off\n");
        }
        
        // 设置命令返回值为0
        cmdret = 0;
    }
     //开启
            //event = LOS_EventWrite(&event_wild, 0x00000001);
            //event = LOS_EventWrite(&event_water, 0x00000001);
            //关闭
            //event = LOS_EventWrite(&event_wild, 0x10000001);      
            //event = LOS_EventWrite(&event_water, 0x10000001); 


EXIT:
    cJSON_Delete(obj_root);
EXIT_JSONPARSE:
    cmdresp.paras = NULL;
    cmdresp.request_id = cmd->request_id;
    cmdresp.ret_code = cmdret;
    cmdresp.ret_name = NULL;
    oc_mqtt_profile_kv_t para1;
    char *key1="result",*value1="success";
    para1.key=key1;
    para1.value=value1;
    para1.nxt=NULL;
    para1.type=EN_OC_MQTT_PROFILE_VALUE_STRING;

    cmdresp.paras = &para1;
    cmdresp.ret_name = "COMMAND_RESPONSE";
    char *deviceid=USERNAME;
    //printf("%x\n",cmdresp.request_id);
    // printf("reid=%s\n",reid);
    // cmdresp.request_id=reid1;
    // printf("%s\n",cmdresp.request_id);
    // printf("deviceid=%s\n",deviceid);
    // printf("%s\n",cmd->request_id);
    // char *id=cmd->request_id;
    // printf("id=%s\n",id);
    // printf("%s\n",cmdresp.request_id);
     int ret=oc_mqtt_profile_cmdresp(deviceid, &cmdresp);

    printf("消息上报结果  ret=%d\n",ret);
}

/***************************************************************
* 函数名称: iot_cloud_ia_thread
* 说    明: 华为云智慧农业线程
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void iot_cloud_ia_thread()
{
    uint8_t hwaddr[6]  = {0x10, 0xdc, 0xb6, 0x90, 0x00, 0x00};
    ia_msg_t *app_msg = NULL;
    unsigned int addr;
    int ret;
    char *reqId = NULL;

    // 初始化Flash
    FlashInit(); 
    // 设置厂商ID和MAC地址
    VendorSet(VENDOR_ID_MAC,               hwaddr,         6);  // 多人同时做该实验，请修改各自不同的WiFi MAC地址
    // 设置WiFi路由器的SSID和密码
    VendorSet(VENDOR_ID_WIFI_ROUTE_SSID,   ROUTE_SSID,     sizeof(ROUTE_SSID));
    VendorSet(VENDOR_ID_WIFI_ROUTE_PASSWD, ROUTE_PASSWORD, sizeof(ROUTE_PASSWORD));
    // 设置WiFi模式为开启
    SetWifiModeOn();

    // 初始化设备信息
    device_info_init(CLIENT_ID, USERNAME, PASSWORD);
    // 初始化MQTT
    ret = oc_mqtt_init();
    if (ret != LOS_OK)
    {
        printf("oc_mqtt_init fail ret:%d\n", ret);
    }
    // 设置命令响应回调函数
    oc_set_cmd_rsp_cb(ia_cmd_response_callback);
    //printf("app_msg->cmd.payload:\n",app_msg->cmd.payload);

    while (1)
    {
        // 从消息队列中读取消息
        ret = LOS_QueueRead(m_ia_MsgQueue, (void *)&addr, BUFFER_LEN, LOS_WAIT_FOREVER);
       // printf("%s\n",addr->cmd.payload);
        
        if (ret == LOS_OK)
        {
            // 将消息地址赋值给app_msg
            app_msg = addr;
            app_msg->report.soil=iosoild_status;
            //printf("app_msg->cmd.payload:\n",app_msg->cmd.payload);
             //printf("app_msg:%s\n",app_msg->cmd.request_id);
            // 根据消息类型进行处理
            switch (app_msg->msg_type)
            {
                case en_msg_cmd:
                    // 处理命令消息
                    ia_deal_cmd_msg(&app_msg->cmd);
                    break;
                case en_msg_report:
                    // 处理上报消息
                    ia_deal_report_msg(&app_msg->report);
                    break;
                default:
                    break;
            }
            // 释放消息内存
            free(app_msg);
            app_msg = NULL;
        }
        else
        {
            // 如果读取失败，则休眠100ms
            LOS_Msleep(100);
        }
    }
}

/***************************************************************
* 函数名称: e53_ia_thread
* 说    明: E53智慧农业线程
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void e53_ia_thread()
{
    ia_msg_t *app_msg = NULL;
    unsigned int ret = LOS_OK;
    unsigned int event;

    e53_ia_init();
/**************************************** */


    //等待LCD初始化完成
    LOS_EventRead(&lcd_event, 0x10000001, LOS_WAITMODE_AND, LOS_WAIT_FOREVER);



/**************************************** */
    while (1)
    {
        e53_ia_read_data(&e53_ia_data);
        app_msg = malloc(sizeof(ia_msg_t));
        if (app_msg != NULL)
        {
            app_msg->msg_type = en_msg_report;
            app_msg->report.hum = (int)e53_ia_data.humidity;
            app_msg->report.lum = (int)e53_ia_data.luminance;
            app_msg->report.temp = (int)e53_ia_data.temperature;
            if (LOS_QueueWrite(m_ia_MsgQueue, (void *)app_msg, sizeof(ia_msg_t), LOS_WAIT_FOREVER) != LOS_OK)
            {
                printf("%s LOS_QueueWrite fail\n", __func__);
                free(app_msg);
            }
        }
        
/**************************************** */
        ret = LOS_QueueWriteCopy(lcd_msg, (void *)&e53_ia_data, sizeof(e53_ia_data), LOS_WAIT_FOREVER);
        //读取并打印
        if (LOS_OK != ret)
        {
            printf("%s write Message Queue msg fail ret:0x%x\n", __func__, ret);
        }
        else
        {
            printf("写入 亮度:%f 湿度:%f 温度：%f\n",e53_ia_data.luminance,e53_ia_data.humidity,e53_ia_data.temperature);
        }
        
            //开启
            //event = LOS_EventWrite(&event_wild, 0x00000001);
            //event = LOS_EventWrite(&event_water, 0x00000001);
            //关闭
            //event = LOS_EventWrite(&event_wild, 0x10000001);      
            //event = LOS_EventWrite(&event_water, 0x10000001);      
/**************************************** */

        LOS_Msleep(5000);
    }
}

/***************************************************************
* 函数名称: iot_cloud_ia_example
* 说    明: 华为云智慧农业例程
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void iot_cloud_ia_example()
{
    unsigned int ret = LOS_OK;
    unsigned int thread_id1;
    unsigned int thread_id2;
    TSK_INIT_PARAM_S task1 = {0};
    TSK_INIT_PARAM_S task2 = {0};

/**************************************** */

    /**队列 */
    //云消息队列
    ret = LOS_QueueCreate("queue", MSG_QUEUE_LENGTH, &m_ia_MsgQueue, 0, BUFFER_LEN);
    if (ret != LOS_OK)
    {
        printf("Falied to create Message Queue ret:0x%x\n", ret);
        return;
    }
    //E53消息队列
    ret = LOS_QueueCreate("queue", MSG_QUEUE_LENGTH, &lcd_msg, 0, BUFFER_LEN);
    if (ret != LOS_OK)
    {
        printf("Falied to create Message Queue ret:0x%x\n", ret);
        return;
    }
    
    /**事件 */
    //风扇控制事件
    ret = LOS_EventInit(&event_wild);
    if (ret != LOS_OK)
    {
        printf("Falied to create EventFlags\n");
        return;
    }
    //水泵控制事件
    ret = LOS_EventInit(&event_water);
    if (ret != LOS_OK)
    {
        printf("Falied to create EventFlags\n");
        return;
    }

/**************************************** */
    
    
    
    
    /**启动线程 */
    task1.pfnTaskEntry = (TSK_ENTRY_FUNC)iot_cloud_ia_thread;
    task1.uwStackSize = 10240;
    task1.pcName = "iot_cloud_ia_thread";
    task1.usTaskPrio = 0;
    ret = LOS_TaskCreate(&thread_id1, &task1);
    if (ret != LOS_OK)
    {
        printf("Falied to create iot_cloud_ia_thread ret:0x%x\n", ret);
        return;
    }

    task2.pfnTaskEntry = (TSK_ENTRY_FUNC)e53_ia_thread;
    task2.uwStackSize = 2048;
    task2.pcName = "e53_ia_thread";
    task2.usTaskPrio = 25;
    ret = LOS_TaskCreate(&thread_id2, &task2);
    if (ret != LOS_OK)
    {
        printf("Falied to create e53_ia_thread ret:0x%x\n", ret);
        return;
    }
}

APP_FEATURE_INIT(iot_cloud_ia_example);
